package com.jdzy.student.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdzy.common.constants.CommonConstants;
import com.jdzy.common.constants.PatentConstants;
import com.jdzy.common.exception.DeleteException;
import com.jdzy.model.common.dtos.PageRequestDto;
import com.jdzy.model.common.vos.PageResult;
import com.jdzy.model.common.vos.Result;
import com.jdzy.model.student.dtos.PatentDeleteDto;
import com.jdzy.model.student.dtos.PatentDto;
import com.jdzy.model.student.dtos.PatentRearchDto;
import com.jdzy.model.student.pojos.Patent;
import com.jdzy.model.student.pojos.PatentOwner;
import com.jdzy.model.student.vos.PatentVo;
import com.jdzy.student.mapper.PatentMapper;
import com.jdzy.student.mapper.PatentOwnerMapper;
import com.jdzy.student.service.PatentService;
import com.jdzy.utils.common.ParseToListOrStringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
@RequiredArgsConstructor
public class PatentServiceImpl extends ServiceImpl<PatentMapper, Patent> implements PatentService {
    private  final  PatentMapper patentMapper;

    private  final  PatentOwnerMapper patentOwnerMapper;

    @Override
    public Result getPatentByStuId(String stuId, Integer page, Integer size, PatentRearchDto patentRearchDto) {

        //1、检查参数
        if(StringUtils.isBlank(stuId)){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //设置分页
        PageRequestDto pageRequestDto=new PageRequestDto(page,size);
        pageRequestDto.checkParam();
        //分页查询
        IPage iPage=new Page(pageRequestDto.getPage(),pageRequestDto.getSize());

        //条件查询
        LambdaQueryWrapper<Patent> patentLambdaQueryWrapper = Wrappers.<Patent>lambdaQuery()
                .eq(Patent::getStuId, stuId)
                .like(StringUtils.isNotBlank(patentRearchDto.getRegistrationNumber()),Patent::getRegistrationNumber,patentRearchDto.getRegistrationNumber())
                //大于等于创建时间之后
                .ge(patentRearchDto.getCreatePatentTime()!=null,Patent::getCreatePatentTime,patentRearchDto.getCreatePatentTime())
                .like(StringUtils.isNotBlank(patentRearchDto.getPatentName()),Patent::getPatentName,patentRearchDto.getPatentName())
                .eq(patentRearchDto.getPatentStatus()!=null,Patent::getPatentStatus,patentRearchDto.getPatentStatus())
                .eq(patentRearchDto.getPatentType()!=null,Patent::getPatentType,patentRearchDto.getPatentType())
                .le(patentRearchDto.getPatentStartTime()!=null, Patent::getPatentStartTime,patentRearchDto.getPatentStartTime()
                );

        //2.2、 若是查找 进行将字符串patentOwnerStr转换为List
        List<String> patentOwners = ParseToListOrStringUtils
                .parseToListWithString(patentRearchDto.getPatentOwnerStr(), PatentConstants.PATENT_SPILT);
        //从patentOwner根据OwnerStr姓名精确查找获取到patent的id号
        List<Long> patentIdList = patentOwnerMapper.getPatentIdListByOwnerName(stuId, patentOwners);
        //2.3、此时根据拥有者表找到了对应的patentId  此时查询拥有者就是精确查找
        /*
        当输入的查找人字符串不为空且没有找到  则直接返回空(注意  这里不能约掉 这里必须进行这个判断  因为当patentIdList为空 默认就是不在意这条条件了)
        所以这行非常重要
         */
        if(StringUtils.isNotBlank(patentRearchDto.getPatentOwnerStr())
                && patentIdList==null || patentIdList.size()==0){
            //封装分页信息
            PageResult pageResult=new PageResult(pageRequestDto.getPage(),pageRequestDto.getSize(),iPage.getTotal());
            return pageResult;
        }

        // 加入到条件查询中
        patentLambdaQueryWrapper.in(patentIdList!=null && patentIdList.size()!=0
                ,Patent::getId,patentIdList);


        //3、进行分页查询
        IPage selectPage = patentMapper.selectPage(iPage,patentLambdaQueryWrapper);
        List<Patent> patents = selectPage.getRecords();

        //进行数据拷贝
        List<PatentVo> patentVos=new ArrayList<>();
        for (Patent patent:patents) {
            PatentVo patentVo=new PatentVo();
            BeanUtils.copyProperties(patent,patentVo);
            //4、从patent根据patentid获取到参与者
            List<String> patentOwnerNameList = patentOwnerMapper.getPatentOwnerName(patent.getId());
            //5、转换成字符串形式
            String patentOwnerNameStr = ParseToListOrStringUtils
                    .parseToString(patentOwnerNameList, PatentConstants.PATENT_SPILT);
            //6、加入到vo类中
            patentVo.setPatentOwnerStr(patentOwnerNameStr);
            patentVos.add(patentVo);
        }

        //3、封装分页信息
        PageResult pageResult=new PageResult(pageRequestDto.getPage(),pageRequestDto.getSize(),iPage.getTotal());
        pageResult.setData(patentVos);
        return pageResult;
    }

    /**
     * 删除专利根据id
     * @param stuId
     * @param patentDeleteDto
     * @return
     */
    @Override
    public Result deletePatent(String stuId, PatentDeleteDto patentDeleteDto) {
        //1、检查参数
        if(StringUtils.isBlank(stuId) || patentDeleteDto==null || patentDeleteDto.getPatentIds().isEmpty()){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //2、进行操作
        synchronized ("deletePatent"+CommonConstants.LOCK_INDEX+ stuId){
            //2.1、判断数据库中有没有这些数据
            List<Patent> patents = patentMapper.selectList(Wrappers.<Patent>lambdaUpdate()
                    .eq(Patent::getStuId, stuId)
                    .in(Patent::getId, patentDeleteDto.getPatentIds()));
            if(patents.size()!=patentDeleteDto.getPatentIds().size()){
                //数据数量对不上
                return Result.error(CommonConstants.DATASOURCE_IS_NULL);
            }
            //2、1进行删除数据
            int delete = patentMapper.delete(Wrappers.<Patent>lambdaUpdate()
                    .eq(Patent::getStuId, stuId)
                    .in(Patent::getId, patentDeleteDto.getPatentIds())
            );
            try {
                if(delete!=patentDeleteDto.getPatentIds().size()){
                    //删除数据量对不上  报错 回滚事务
                    throw new DeleteException();
                }
                //删除拥有者表信息
                patentOwnerMapper.delete(Wrappers.<PatentOwner>lambdaQuery()
                        .in(patentDeleteDto.getPatentIds().size()!=0,PatentOwner::getPatentId,patentDeleteDto.getPatentIds())
                        .eq(PatentOwner::getStuId,stuId)
                );
            }catch (DeleteException deleteException){
                //手动回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                log.error("deletePatent---->删除数据量对不上");
                return Result.error(CommonConstants.DELETE_FAIL);
            }
        }
        return Result.success();
    }

    /**
     * 保存专利信息
     * @param patentDto
     * @return
     */
    @Override
    public Result savePatent(PatentDto patentDto) {
        //1、检查参数
        if(patentDto==null || StringUtils.isBlank(patentDto.getStuId())
                || StringUtils.isBlank(patentDto.getPatentName())){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //2、进行参数拷贝
        Patent patent=new Patent();
        BeanUtils.copyProperties(patentDto,patent);
        //3、进行插入数据库
        int insert = patentMapper.insert(patent);
        if(insert==0){
            return Result.error(CommonConstants.INSERT_FAIL);
        }
        //4、插入到拥有者表中
        List<String> PatentOwners = ParseToListOrStringUtils.parseToListWithString(patentDto.getPatentOwnerStr()
                , PatentConstants.PATENT_SPILT);

        for (String patentOwnerStr : PatentOwners) {
            PatentOwner patentOwner=new PatentOwner();
            patentOwner.setStuId(patentDto.getStuId());
            patentOwner.setPatentId(patent.getId());
            patentOwner.setPatentOwnerName(patentOwnerStr);

//            copyrightOwnerList.add(copyrightOwner);
            patentOwnerMapper.insert(patentOwner);
        }
        return Result.success();
    }

    /**
     * 修改专利信息
     * @param patentDto
     * @return
     */
    @Override
    public Result updatePatent(PatentDto patentDto) {
        //1、检查参数
        if(patentDto==null || patentDto.getId()==null || StringUtils.isBlank(patentDto.getStuId())){
            return Result.error(CommonConstants.PARAM_REQUIRE);
        }
        //2、查询数据库中有无该数据
        Patent patent = patentMapper.selectOne(Wrappers.<Patent>lambdaQuery()
                .eq(Patent::getId, patentDto.getId())
                .eq(Patent::getStuId, patentDto.getStuId()));
        if(patent==null){
            return Result.error(CommonConstants.DATASOURCE_IS_NULL);
        }
        synchronized ("updatePatent"+CommonConstants.LOCK_INDEX+patentDto.getId()
                +CommonConstants.LOCK_INDEX+patentDto.getStuId()){
            //3、参数拷贝
            BeanUtils.copyProperties(patentDto,patent);
            //4、进行修改
            int updateById = patentMapper.updateById(patent);

            if(updateById==0){
                return Result.error(CommonConstants.UPDATE_FAIL);
            }

            //4、修改成功  修改PatentOwner表
            //4.1、修改PatentOwner表获取老旧信息
            List<String> oldPatentOwnerNames = patentOwnerMapper.getPatentOwnerName(patentDto.getId());

            //4.2、以防有重名人  用Map进行统计
            Map<String,Integer> oldPatentOwnerNameMap=new HashMap<>();
            for (String oldPatentOwnerName : oldPatentOwnerNames) {
                oldPatentOwnerNameMap.put(oldPatentOwnerName,oldPatentOwnerNameMap
                        .getOrDefault(oldPatentOwnerName,0)+1);
            }
            /*
            这里和前端商议好了 字符串传递  并商议好 "," 为分割
             */
            List<String> newPatentOwnerNames = ParseToListOrStringUtils.parseToListWithString(patentDto
                    .getPatentOwnerStr(), PatentConstants.PATENT_SPILT);
            patentDto.setPatentOwners(newPatentOwnerNames);
            //4、3同样将传入的数据进行转换成Map
            Map<String,Integer> newPatentOwnerNameMap=new HashMap<>();
            for (String newPatentOwnerName : newPatentOwnerNames) {
                newPatentOwnerNameMap.put(newPatentOwnerName,newPatentOwnerNameMap
                        .getOrDefault(newPatentOwnerName,0)+1);
            }

            //4、4  比较两个Map是否相等
            if(oldPatentOwnerNameMap.equals(newPatentOwnerNameMap)){
                return Result.success();
            }else{
                //4.5、不一样   图方便全部删除
                patentOwnerMapper.delete(Wrappers.<PatentOwner>lambdaQuery()
                        .in(PatentOwner::getPatentId,patentDto.getId())
                );
                //4.6、开始插入新的数据
                if(newPatentOwnerNames.size()==0){
                    return Result.success();
                }else{
                    for (String newPatentOwnerName : newPatentOwnerNames) {
                        PatentOwner patentOwner=new PatentOwner();
                        patentOwner.setStuId(patentDto.getStuId());
                        patentOwner.setPatentId(patentDto.getId());
                        patentOwner.setPatentOwnerName(newPatentOwnerName);

                        patentOwnerMapper.insert(patentOwner);
                    }
                }
            }
        }

        return Result.success();
    }

}
